#ifndef SEMANTIC_H
#define SEMENTIC_H

#define HASH_TABLE_SIZE 0x3fff
#define STACK_DEEP

#include "node.h"

typedef struct type* pType;//类型指针
typedef struct fieldList* pFieldList;//域指针
typedef struct tableItem* pItem;//十字链表指针
typedef struct hashTable* pHash;//hash表指针
typedef struct stack* pStack;//栈指针,用栈来判断变量作用域
typedef struct table* pTable;//符号表指针
//类型
typedef struct type {
    Kind kind;
    union {
        // 基本类型
        BasicType basic;
        // 数组类型信息;包括元素类型与数组大小
        struct {
            pType elem;
            int size;
        } array;
        // 结构体类型;一个链表
        struct {
            char* structName;
            pFieldList field;
        } structure;
	// 函数类型;包括参数个数，参数列表，返回值类型
        struct {
            int argc;          
            pFieldList argv;   
            pType returnType; 
        } function;
    } u;
} Type;
//域节点
typedef struct fieldList {
    char* name;       // 域名
    pType type;       // 域类
    pFieldList tail;  // 下一个域
} FieldList;
//十字链表
typedef struct tableItem {
    int symbolDepth;
    pFieldList field;
    pItem nextSymbol;  // 相同深度下一个符号，从栈链接
    pItem nextHash;    // 相同hash值的下一个符号，从哈希表链接
} TableItem;
//哈希表
typedef struct hashTable {
    pItem* hashArray;
} HashTable;
//栈
typedef struct stack {
    pItem* stackArray;
    int curStackDepth;
} Stack;
//符号表：hash表存储变量符号,十字链表确定作用域
typedef struct table {
    pHash hash;
    pStack stack;
    int unNamedStructNum;
} Table;

extern pTable table;
/*
对每个结构体封装了对应的操作方法，包括基本的 new（构造新的结构体）;delete（释放结构体内存空间）;copy（拷贝结构体（均为深拷贝））;部分结构体特有的方法。
*/
// Type 相关方法
pType newType(Kind kind, ...);
pType copyType(pType src);
void deleteType(pType type);
//判断两个类型是否相同
boolean checkType(pType type1, pType type2);

// FieldList 相关方法
pFieldList newFieldList(char* newName, pType newType);
pFieldList copyFieldList(pFieldList src);
void deleteFieldList(pFieldList fieldList);
//设置name
void setFieldListName(pFieldList p, char* newName);

// tableItem 相关方法
pItem newItem(int symbolDepth, pFieldList pfield);
void deleteItem(pItem item);
boolean isStructDef(pItem src);

// hash 相关方法
pHash newHash();
void deleteHash(pHash hash);
// 获得下标为index的hash表中的元素
pItem getHashHead(pHash hash, int index);
// 设置下标为index的hash表中的元素
void setHashHead(pHash hash, int index, pItem newVal);

// stack 相关方法
pStack newStack();
void deleteStack(pStack stack);
// 栈深加一
void addStackDepth(pStack stack);
// 栈深减一
void minusStackDepth(pStack stack);
// 获得当前栈深度位置的元素
pItem getCurDepthStackHead(pStack stack);
// 设置当前栈深度位置的元素
void setCurDepthStackHead(pStack stack, pItem newVal);

// table 相关方法
pTable initTable();
void deleteTable(pTable table);
// 在table中查找名字为name的符号
pItem searchTableItem(pTable table, char* name);
// 检查新的符号是否与之前定义过的符号冲突
boolean checkTableItemConflict(pTable table, pItem item);
// 向table中增加一个符号
void addTableItem(pTable table, pItem item);
// 向table中删除一个符号
void deleteTableItem(pTable table, pItem item);
// 清除当前栈深度的所有符号
void clearCurDepthStackList(pTable table);

// 别的全局函数
//hash函数
static inline unsigned int getHashCode(char* name) {
    unsigned int val = 0, i;
    for (; *name; ++name) {
        val = (val << 2) + *name;
        if (i = val & ~HASH_TABLE_SIZE)
            val = (val ^ (i >> 12)) & HASH_TABLE_SIZE;
    }
    return val;
}
//打印错误信息
static inline void pError(ErrorType type, int line, char* msg) {
    printf("Error type %d at Line %d: %s\n", type, line, msg);
}
//遍历树
void traverseTree(pNode node);

// 构造好树之后，自顶向下语法递归分析的函数
// 全局变量，结构体，函数的单个定义
void ExtDef(pNode node);
// 0个或多个ExtDef
void ExtDecList(pNode node, pType specifier);
// 类型描述符，基本类型或者结构体
pType Specifier(pNode node);
// 结构体
pType StructSpecifier(pNode node);
// 定义变量
pItem VarDec(pNode node, pType specifier);
// 定义函数头
void FunDec(pNode node, pType returnType);
// 0个或多个ParamDec
void VarList(pNode node, pItem func);
// 定义形参
pFieldList ParamDec(pNode node);
// 花括号括起来的语句块
void CompSt(pNode node, pType returnType);
// 0个或多个Stmt
void StmtList(pNode node, pType returnType);
// 语句
void Stmt(pNode node, pType returnType);
// 0个或多个Def
void DefList(pNode node, pItem structInfo);
// 定义局部变量
void Def(pNode node, pItem structInfo);
// 0个或多个Dec
void DecList(pNode node, pType specifier, pItem structInfo);
// 变量定义
void Dec(pNode node, pType specifier, pItem structInfo);
// 表达式
pType Exp(pNode node);
// 实参列表
void Args(pNode node, pItem funcInfo);

#endif
